

/**
 * 虚拟滚动组件
 * @date 2025/11/19 20:00:41
 * @author lyqjob@yeah.net
 */

import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react';
import { Spin, Space, Card, Select, Slider, Button, Segmented, Typography, BackTop, Skeleton, message } from 'antd';
import styles from '../index.less';

const itemHeight = 150; // 每个item的高度
const BUFFER = 5; // 缓冲区数量
const MARGIN = 20; // 缓冲区高度，用于计算总高度

const VirtualScroll = () => {
    const scrollContainerRef = useRef(null);
    const [loading, setLoading] = useState(false);
    const [data, setData] = useState([]);
    const [scrollTop, setScrollTop] = useState(0);
    const [viewportH, setViewportH] = useState(600); // 设置默认高度

    // 计算总高度
    const totalHeight = useMemo(() => {
        return data.length * (itemHeight + MARGIN)
    }, [data.length]);

    // 计算开始和结束索引
    const startIndex = useMemo(() => Math.max(0, Math.floor(scrollTop / (itemHeight + MARGIN)) - BUFFER), [scrollTop]);
    const endIndex = useMemo(() => Math.min(data.length, startIndex + BUFFER * 2 + Math.ceil(viewportH / (itemHeight + MARGIN))), [data.length, startIndex, viewportH]);

    // 计算需要渲染的数据
    const slice = useMemo(() => data.slice(startIndex, endIndex), [data, startIndex, endIndex]);

    // 优化滚动处理，不使用防抖以保证流畅性
    const handleScroll = useCallback((e) => {
        const newScrollTop = e.target.scrollTop;
        setScrollTop(newScrollTop);
    }, []);

    useEffect(() => {
        const el = scrollContainerRef.current;
        if (!el) return;

        // 获取滚动容器的高度
        const updateViewportHeight = () => {
            if (el) {
                const height = el.clientHeight;
                setViewportH(height);
                console.log('滚动容器高度', height);
            }
        };

        updateViewportHeight();
        
        // 添加滚动事件监听器，使用passive选项来提高性能
        el.addEventListener('scroll', handleScroll, { passive: true });
        
        // 监听窗口大小变化
        window.addEventListener('resize', updateViewportHeight);

        // 初始化数据
        mockData();

        // 清理事件监听器
        return () => {
            el.removeEventListener('scroll', handleScroll);
            window.removeEventListener('resize', updateViewportHeight);
        };
    }, [handleScroll]);





    // 模拟数据
    const mockData = () => {
        const data = [];
        for (let i = 0; i < 10000; i++) {
            data.push({
                id: i,
                title: `标题${i}`,
                content: `内容${i}`,
            });
        }
        console.log('mockData', data);
        setData(data);
    }


    return (
        <div className={styles.container}>
            <div className={styles.header}>
                <h2>虚拟滚动演示</h2>
                <p>总数据量: {data.length} 条，当前显示: {startIndex} - {endIndex} 条</p>
            </div>
            <div 
                // className={styles.main} 
                ref={scrollContainerRef}
                style={{ 
                    flex: 1,
                    paddingTop: 10,
                    overflow: 'auto',
                    position: 'relative',
                    border: '1px solid #d9d9d9',
                    borderRadius: '6px',
                    backgroundColor: '#fafafa'
                }}
            >
                {/* 占位元素，撑开滚动条高度 */}
                <div style={{ height: totalHeight, position: 'relative' }}>
                    {/* 实际渲染的元素 */}
                    <div 
                        style={{ 
                            transform: `translateY(${startIndex * (itemHeight + MARGIN)}px)`,
                            position: 'absolute',
                            top: 0,
                            left: 0,
                            right: 0
                        }}
                    >
                        {slice.map((item, index) => (
                            <Card 
                                style={{ 
                                    height: itemHeight, 
                                    marginBottom: MARGIN,
                                    marginRight: MARGIN,
                                    marginLeft: MARGIN
                                }} 
                                key={`${startIndex + index}-${item.id}`} 
                                title={item.title}
                                size="small"
                            >
                                {item.content}
                            </Card>
                        ))}
                    </div>
                </div>
            </div>
        </div>
    )
}

export default VirtualScroll;